#include <iostream>
#include <memory>

// 抽象电脑类
class Computer
{
public:
    Computer(){}
    void setBoard(const std::string& board)
    {
        _board = board;
    }

    void setDisplay(const std::string& display)
    {
        _display = display;
    }

    virtual void setOs() = 0;

    void showParameters()
    {
        std::string computer = "Computer:{\n";
        computer += "\t board=" + _board + "\n";
        computer += "\t display=" + _display + "\n";
        computer += "\t os=" + _os + "\n}\n";

        std::cout << computer;
    }

protected:
    std::string _board;
    std::string _display;
    std::string _os;
};

// 具体产品类
class MacBook :public Computer
{
public:
    MacBook(){}
    virtual void setOs()
    {
        _os = "Max Os X12";
    }
};

// 抽象建造者类，包含创建对象的各个部件的抽象接口
class Builder
{
public:
    virtual void buildBoard(const std::string& board) = 0;
    virtual void buildDisplay(const std::string& display) = 0;
    virtual void buildOs() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};

// 具体建造者
class MacBookBuilder :public Builder
{
public:
    MacBookBuilder() :_computer(new MacBook()){}
    // 建造零件
    virtual void buildBoard(const std::string& board)
    {
        _computer->setBoard(board);
    }

    virtual void buildDisplay(const std::string& display)
    {
        _computer->setDisplay(display);
    }

    virtual void buildOs()
    {
        _computer->setOs();
    }

    std::shared_ptr<Computer> build()
    {
        return _computer;
    }

private:
    std::shared_ptr<Computer> _computer;
};

// 指挥者类，提供给调用者使用，通过指挥者构造复杂产品
// 统一建造顺序
class Director
{
public:
    Director(Builder* builder) :_builder(builder) {}
    void construct(const std::string& board, const std::string& display)
    {
        _builder->buildBoard(board);
        _builder->buildDisplay(display);
        _builder->buildOs();
    }

private:
    std::shared_ptr<Builder> _builder;
};

int main()
{
    // 具体建造者
    Builder *build = new MacBookBuilder();
    std::unique_ptr<Director> dir(new Director(build));
    dir->construct("华硕主板", "三星显示器");
    std::shared_ptr<Computer> computer = build->build();
    computer->showParameters();
}